package com.sikaryofficial.system.service.impl;

import cn.hutool.core.text.CharSequenceUtil;
import com.ip2location.IP2Location;
import com.ip2location.IPResult;
import com.sikaryofficial.common.redis.service.RedisService;
import com.sikaryofficial.system.api.model.ip.IpLocationVO;
import com.sikaryofficial.system.constant.RedisCacheKey;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.text.MessageFormat;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

/**
 * @author : qinjinyuan
 * @desc : IP国家信息服务
 * @date : 2024/07/26 16:25
 */
@Service
@Slf4j
@SuppressWarnings(value = "unchecked")
public class Ip2LocationService {

    @Value("${ip2location.ip2location-lite-db1_path}")
    private String db1Path;
    /**
     * 国家 区域 市 三级数据
     */
    @Value("${ip2location.ip2location-lite-db3_path}")
    private String db3Path;

    @Autowired
    private RedisService redisService;

    /**
     * 将IP地址字符串分割成四个部分，每一部分都是一个0到255之间的整数。
     * 将这四个整数分别左移相应的位数，然后相加得到最终的整数值
     *
     * @param ipAddress
     * @return
     */
    private Integer ipToInteger(String ipAddress) {
        return IntStream.range(0, 4)
                .map(i -> (256 - 256 / (int) Math.pow(256, i)) * Integer.parseInt(ipAddress.split("\\.")[i]))
                .reduce(0, Integer::sum);
    }

    private String buildIpDB1CacheKey(String iPAddress) {
        return MessageFormat.format(RedisCacheKey.IP_LOCATION_DB1_CACHE, ipToInteger(iPAddress).toString());
    }


    /**
     * 与上面的方法，区别是查询的数据库文件不一样
     * @param iPAddress
     * @return
     */
    public IpLocationVO getGeographyInfo(String iPAddress) {
        if (CharSequenceUtil.isBlank(iPAddress)) {
            return null;
        }
        String cacheKey = buildIpDB1CacheKey(iPAddress);
        if(Boolean.TRUE.equals(redisService.hasKey(cacheKey))){
            log.info("ip2location---cacheKey>{}", cacheKey);
            return redisService.getCacheObject(cacheKey);
        }
        try {
            long startTime = System.currentTimeMillis();
            log.info("ip2location---iPAddress>{}", iPAddress);
            // 加载数据库
            IP2Location db = new IP2Location();
            db.Open(db1Path);
            // 查询 IP 地址
            IPResult ipResult = db.IPQuery(iPAddress);
            IpLocationVO ipLocationVO = ipLocationVOMapper(ipResult);
            redisService.setCacheObject(cacheKey, ipLocationVO, 12L, TimeUnit.HOURS);
            // 关闭数据库
            db.Close();
            log.info("ip2location---cost-->{}", System.currentTimeMillis() - startTime);
            log.info("countryCOde--->{}", ipLocationVO.getCountryCode());
            return ipLocationVO;
        } catch (Exception e) {
            log.error("ip2location error", e);
        }
        return null;
    }

    private IpLocationVO ipLocationVOMapper(IPResult record) {
        IpLocationVO record1 = new IpLocationVO();
        if(Objects.isNull(record)){
            return record1;
        }
        record1.setRegion(record.getRegion());
        record1.setCity(record.getCity());
        record1.setCountryLong(record.getCountryLong());
        record1.setCountryShort(record.getCountryShort());
        return record1;
    }

}
